import { cx } from '@/utils';
import { Input } from '@arco-design/web-react';
import { CSSProperties, ReactChild, ReactNode, memo, useCallback, useEffect, useMemo, useState } from 'react';
import styles from './Cell.module.scss';
import { TableCellExtra } from './CellExtra';
import { inputFocus, noop, stopPropagation } from './const';
import { ColFixeds, IColumn } from './types';

interface IProps {
  /** 聚焦状态 */
  focus?: boolean;
  /** 编辑状态 */
  edit?: boolean;
  /** 是否可编辑 */
  editable?: boolean;
  /** 表格值 */
  value: ReactNode;
  /** 表格值 */
  dataValue: ReactNode;
  /** 行索引 */
  index: number;
  /** 单元格点击 */
  onCellClick: (index: number, colKey: string | number, isDbClick?: boolean) => void;
  /** 移除聚焦单元格 */
  onEditBlur?: () => void;
  /** 列配置 */
  column: IColumn;
  /**
   * 单元格输入触发，input输入值改变时触发
   * @param dataRow 当前渲染的数据行
   * @param dataKey 数据的key
   * @param val 编辑输入框的值
   * @returns
   */
  onCellChange?: (dataRow: number, dataKey: string | number, val: any, rowKey: any) => void;
  /**
   * 单元格失去焦点时触发
   * @param dataRow 当前渲染的数据行
   * @param dataKey 数据的key
   * @param val 编辑输入框的值
   * @returns
   */
  onBlur?: (dataRow: number, dataKey: string | number, val: any, rowKey: any) => void;
  /** 额外展示内容 */
  extraContent?: ReactChild;
  /** 额外展示内容2 */
  extraContent2?: ReactChild;
  /** 行数据 */
  data: any;
  /** 固定列配置 */
  colFixed: ColFixeds;
  /** footer 样式目前不支持修改 */
  footerStyle?: React.CSSProperties,
}

const editInputStyle = { width: '100%' };

/**
 * 单元格
 */
const Cell = memo((props: IProps) => {
  const { focus, edit, value, dataValue, index, onCellClick, onEditBlur, column, onCellChange, extraContent, extraContent2, data, colFixed, footerStyle, editable, onBlur } = props;
  const { key, bodyCellStyle } = column;
  const [editVal, setEditVal] = useState('');

  const onClick = useCallback((evt: any) => {
    evt.stopPropagation();
    onCellClick(index, key, true);
  }, [index, onCellClick, key]);

  // const onDbClick = useCallback((evt: any) => {
  //   evt.stopPropagation();
  //   onCellClick(index, key, true);
  // }, [index, onCellClick, key]);

  const fixed = useMemo(() => colFixed[column.key], [colFixed, column]);

  const cls = useMemo(() => {
    return cx({
      [styles.cell]: true,
      [styles.focus]: focus,
      [styles.edit]: edit,
      [styles.editable]: editable,
      [styles.fixedRight]: fixed ? fixed.isRight : false,
      [styles.fixedLeft]: fixed ? fixed.isLeft : false,
      [styles.first]: fixed ? fixed.first : false,
      [`c_${column.key}`]: true, // TODO: 是否无用
    });
  }, [focus, edit, column.key, editable, fixed]);

  useEffect(() => {
    if (focus) {
      if (typeof value === 'object') {
        setEditVal(dataValue + '');
      } else {
        setEditVal(value + '');
      }
    }
  }, [focus, value, dataValue]);

  const content = edit ? (
    <Input
      className={styles.input}
      style={editInputStyle}
      height={'100%'}
      autoFocus
      onFocus={inputFocus}
      value={editVal}
      onChange={(val) => {
        onCellChange && onCellChange(index, column.key, val, data.key || data.ID || data.id);
        setEditVal(val);
      }}
      onBlur={(event: any) => {
        onEditBlur && onEditBlur()
        onBlur && onBlur(index, column.key, event.target.value, data.key || data.ID || data.id);
        setEditVal(event.target.value);
      }}
      onKeyDown={(event: any) => {
        if (event.key == 'ArrowUp' || event.key == 'ArrowDown' || event.key == 'ArrowLeft' || event.key == 'ArrowRight') {
          onBlur && onBlur(index, column.key, event.target.value, data.key || data.ID || data.id);
          setEditVal(event.target.value);
        }
      }}
    />
  ) : value;

  const extra = useMemo(() => {
    if (column.extra) {
      return (
        extraContent && <TableCellExtra color={column.extraColor || '#0045d7'} placement={column.extraPlacement || 'bottomRight'}>{extraContent}</TableCellExtra> || null
      );
    }
    return null;
  }, [
    column.extraPlacement, column.extraColor, extraContent
  ]);

  const extra2 = useMemo(() => {
    if (column.extra2) {
      return (
        extraContent2 && <TableCellExtra color={column.extraColor || '#d10000'} placement={column.extraPlacement || 'topLeft'}>{extraContent2}</TableCellExtra> || null
      );
    }
    return null;
  }, [
    column.extraPlacement, column.extraColor, extraContent2
  ]);

  const colSpan = useMemo(() => {
    if (column.colSpan) {
      return column.colSpan(value, data, index);
    }
  }, [column.colSpan, value, data]);

  const rowSpan = useMemo(() => {
    if (column.rowSpan) {
      return column.rowSpan(value, data, index);
    }
  }, [column.rowSpan, value, data]);

  const style = useMemo(() => {
    if (fixed) {
      return {
        [fixed!.isLeft ? 'left' : 'right']: fixed!.offset,
        ...bodyCellStyle,
        ...footerStyle,
      }
    } else {
      return {
        ...bodyCellStyle,
        ...footerStyle,
      }
    }
  }, [fixed]);

  // 被合并单元格需要隐藏
  if (colSpan === 0 || rowSpan === 0) return null;

  return <td
    colSpan={colSpan}
    rowSpan={rowSpan}
    onClick={editable && !focus ? onClick : editable ? stopPropagation : noop}
    // onDoubleClick={editable && !edit ? onDbClick : editable ? stopPropagation : noop}
    className={cls}
    style={style}
  >
    {content}
    {extra}
    {extra2}
  </td>;
});

export { Cell };
